#include "HttpParser.h"

string HttpParser::s_separator = "\r\n";

void HttpParser::clear() 
{
    m_param.clear();
    m_ingress_capacity = 0;
    m_xmlKV.clear(); 
};

HttpParser::HttpParser() 
{ 
    clear(); 
}

HttpParser::~HttpParser() 
{ 
}

string HttpParser::getXmlValueByKey(const string &key) 
{
    map<string,string>::iterator itor = m_xmlKV.find(key);
    if(itor != m_xmlKV.end()) return itor->second;
    return string("");
}


/**
 * @brief Extract text between start_word and end_word
 *
 * @param text
 * @param start_word
 * @param end_word
 * @param pos Optional position to start searching
 *
 * @return Result of the extraction. Empty string on failure 
 */
string HttpParser::extract_between(string &text, string &start_word, string &end_word, string::size_type pos)
{
    pos = text.find(start_word, pos);
    if (pos == string::npos) return string("");
    pos += start_word.size();
    string::size_type pos_begin = pos;
    pos = text.find(end_word, pos);
    if (pos == string::npos) return string("");
    
    return text.substr(pos_begin, pos - pos_begin);
}

void HttpParser::parseLocatingRequestMsg(string &http_msg)
{
    //extract XML text
    string::size_type pos = 0;
    string keyword = "<?xml";
    pos = http_msg.find(keyword, pos);
    if (pos == string::npos) return;
    string::size_type pos_begin = pos;
    pos += keyword.size();
    keyword = "</LocateRequest>";
    pos = http_msg.find(keyword, pos);
    if (pos == string::npos) return;
    pos += keyword.size();

    parseXml(http_msg.substr(pos_begin, pos - pos_begin));
}

void HttpParser::parseTransferRequestMsg(string &http_msg)
{
    //skip GET the method name
    string keyword = "GET";
    string::size_type pos = http_msg.find(keyword, 0);
    if(pos == string::npos) return;
    pos += keyword.size();

    //get transfer ID
    while (http_msg[pos] == ' ') {
        pos++;
    }

    string::size_type pos_begin = pos;
    while (http_msg[pos] != ' ') {
        pos++;
    }

    m_param = http_msg.substr(pos_begin, pos - pos_begin);

    //get request range
    pos = http_msg.find("Range:", pos);
    keyword = "bytes=";
    string range_text = extract_between(http_msg, keyword, s_separator, pos);
    if(range_text.empty()) return;
    m_range_start = strtol(range_text.c_str(), NULL, 10);
    pos = range_text.find("-");
    if(pos == string::npos) {
        m_range_end = 0;
    } else {
        m_range_end = strtol(range_text.substr(pos+1).c_str(), NULL, 10);
    }

    //get ingress capacity 
    keyword = "Ingress-Capacity:";
    string capacity_text = extract_between(http_msg, keyword, s_separator);
    if(capacity_text.empty()) return;
    m_ingress_capacity = strtol(capacity_text.c_str(), NULL, 10);
}

void HttpParser::parseXml(string xml_text)
{
    if(!xml_text.empty()) {
        TiXmlDocument* doc = new TiXmlDocument();
        doc->Parse(xml_text.c_str());

        TiXmlDeclaration* xmld = doc->FirstChild()->ToDeclaration();
        if(xmld != NULL) {
            m_xmlKV.insert(make_pair("version", xmld->Version()));
            m_xmlKV.insert(make_pair("encoding", xmld->Encoding()));
        }

        TiXmlElement* rootEle = doc->RootElement()->FirstChildElement();
        parseElement(rootEle);

        delete doc;
    }
}

void HttpParser::parseElement(TiXmlElement* xmlEle)
{   
    while(xmlEle) {
        if(xmlEle->FirstChildElement()) {
            parseElement(xmlEle->FirstChildElement());
        } else {
            TiXmlNode *ntemp = xmlEle->FirstChild();
            if(ntemp) {
                m_xmlKV.insert(make_pair(xmlEle->Value(), ntemp->Value()));
            }
        }
        xmlEle = xmlEle->NextSiblingElement();
    }
}


